gumjs_headers = [
  'gumjs.h',
  'gumscript.h',
  'gumscriptbackend.h',
  'gumscriptscheduler.h',
  'guminspectorserver.h',
]

gumjs_sources = [
  'gumjs.c',
  'gumscript.c',
  'gumscriptbackend.c',
  'gumscriptscheduler.c',
  'guminspectorserver.c',
  'gumscripttask.c',
  'gumsourcemap.c',
  'gummemoryvfs.c',
  'gumffi.c',
  'gumcmodule.c',
]

if quickjs_dep.found()
  gumjs_sources += [
    'gumquickscriptbackend.c',
    'gumquickscript.c',
    'gumquickbundle.c',
    'gumquickvalue.c',
    'gumquickobject.c',
    'gumquickcore.c',
    'gumquickkernel.c',
    'gumquickmemory.c',
    'gumquickprocess.c',
    'gumquickthread.c',
    'gumquickmodule.c',
    'gumquickfile.c',
    'gumquickstream.c',
    'gumquicksocket.c',
    'gumquickdatabase.c',
    'gumquickinterceptor.c',
    'gumquickstalker.c',
    'gumquickeventsink.c',
    'gumquickapiresolver.c',
    'gumquicksymbol.c',
    'gumquickcmodule.c',
    'gumquickinstruction.c',
    'gumquickcodewriter.c',
    'gumquickcoderelocator.c',
  ]

  quickcompile = executable('quickcompile', 'gumquickcompile.c',
    dependencies: [quickjs_dep_native],
    native: true,
  )
else
  quickcompile = ''
endif

if v8_dep.found()
  gumjs_sources += [
    'gumv8scriptbackend.cpp',
    'gumv8script.cpp',
    'gumv8platform.cpp',
    'gumv8bundle.cpp',
    'gumv8scope.cpp',
    'gumv8value.cpp',
    'gumv8object.cpp',
    'gumv8core.cpp',
    'gumv8kernel.cpp',
    'gumv8memory.cpp',
    'gumv8process.cpp',
    'gumv8thread.cpp',
    'gumv8module.cpp',
    'gumv8file.cpp',
    'gumv8stream.cpp',
    'gumv8socket.cpp',
    'gumv8database.cpp',
    'gumv8interceptor.cpp',
    'gumv8stalker.cpp',
    'gumv8eventsink.cpp',
    'gumv8apiresolver.cpp',
    'gumv8symbol.cpp',
    'gumv8cmodule.cpp',
    'gumv8instruction.cpp',
    'gumv8codewriter.cpp',
    'gumv8coderelocator.cpp',
  ]
endif

gumjs_generated_origins = [
  'arch-x86/gumx86writer.h',
  'arch-x86/gumx86relocator.h',
  'arch-arm/gumarmwriter.h',
  'arch-arm/gumarmrelocator.h',
  'arch-arm/gumthumbwriter.h',
  'arch-arm/gumthumbrelocator.h',
  'arch-arm64/gumarm64writer.h',
  'arch-arm64/gumarm64relocator.h',
  'arch-mips/gummipswriter.h',
  'arch-mips/gummipsrelocator.h',
]
gumjs_generated_inputs = []
foreach o : gumjs_generated_origins
  gumjs_generated_inputs += join_paths(meson.source_root(), 'gum', o)
endforeach
gumjs_generated_outputs = []
runtimes = []
if quickjs_dep.found()
  runtimes += 'quick'
endif
if v8_dep.found()
  runtimes += 'v8'
endif
autogenerated_modules = [
  'writer',
  'relocator',
]
autogenerated_flavors = [
  'x86',
  'arm',
  'thumb',
  'arm64',
  'mips',
]
autogenerated_sections = [
  '',
  '-fields',
  '-methods',
  '-init',
  '-dispose',
]
foreach r : runtimes
  foreach m : autogenerated_modules
    foreach s : autogenerated_sections
      gumjs_generated_outputs += 'gum@0@code@1@@2@.inc'.format(r, m, s)
      foreach f : autogenerated_flavors
        gumjs_generated_outputs += 'gum@0@code@1@@2@-@3@.inc'.format(r, m, s, f)
      endforeach
    endforeach
  endforeach
endforeach

gumjs_runtime_sources = [
  'runtime/entrypoint-quickjs.js',
  'runtime/entrypoint-v8.js',
  'runtime/core.js',
  'runtime/message-dispatcher.js',
  'runtime/error-handler-quickjs.js',
  'runtime/error-handler-v8.js',
  'runtime/console.js',
  'runtime/hexdump.js',
  'runtime/objc.js',
  'runtime/java.js',
  'runtime/cmodule-tcc/inttypes.h',
  'runtime/cmodule-tcc/stdint.h',
  'runtime/cmodule-tcc/stdio.h',
  'runtime/cmodule-tcc/stdlib.h',
  'runtime/cmodule-tcc/string.h',
  'runtime/cmodule/glib.h',
  'runtime/cmodule/gum/gumdefs.h',
  'runtime/cmodule/gum/gumprocess.h',
  'runtime/cmodule/gum/gummodulemap.h',
  'runtime/cmodule/gum/gummemory.h',
  'runtime/cmodule/gum/guminterceptor.h',
  'runtime/cmodule/gum/gumstalker.h',
  'runtime/cmodule/gum/gummetalarray.h',
  'runtime/cmodule/gum/gummetalhash.h',
  'runtime/cmodule/gum/gumspinlock.h',
  'runtime/cmodule/json-glib/json-glib.h',
]
gumjs_runtime_outputs = [
  'gumquickscript-runtime.h',
  'gumquickscript-objc.h',
  'gumquickscript-java.h',
  'gumv8script-runtime.h',
  'gumv8script-objc.h',
  'gumv8script-java.h',
  'gumcmodule-runtime.h',
]

install_headers(gumjs_headers, subdir: install_header_basedir + '/gumjs')

gumjs_generated_bindings = custom_target('gumjs-generated-bindings',
  input: gumjs_generated_inputs,
  output: gumjs_generated_outputs,
  command: [
    find_program('generate-bindings.py'),
    join_paths(meson.source_root(), 'gum'),
    meson.current_build_dir(),
  ],
)
gumjs_sources += [gumjs_generated_bindings]

gumjs_runtime = custom_target('gumjs-runtime',
  input: gumjs_runtime_sources,
  output: gumjs_runtime_outputs,
  command: [
    find_program('generate-runtime.py'),
    host_arch,
    meson.current_source_dir(),
    meson.source_root() / 'gum',
    capstone_dep.get_variable(pkgconfig: 'includedir') / 'capstone',
    libtcc_dep.found() ? libtcc_dep.get_variable(pkgconfig: 'libdir') : '',
    quickcompile,
    meson.current_build_dir(),
  ],
)
gumjs_sources += [gumjs_runtime]

deps = [
  gum_dep,

  quickjs_dep,
  v8_dep,

  gio_dep,
  gio_os_package_dep,
  json_glib_dep,
  ffi_dep,
  libtcc_dep,
  sqlite_dep,
  libsoup_dep,
]

gumjs = library('frida-gumjs-' + api_version, gumjs_sources,
  c_args: frida_component_cflags,
  override_options: ['cpp_std=c++14'],
  include_directories: [bindings_inc],
  dependencies: deps,
  install: true,
)

gumjs_dep = declare_dependency(link_with: gumjs,
  include_directories: [bindings_inc, include_directories('.')],
  dependencies: deps,
)

pkg = import('pkgconfig')
pkg.generate(filebase: 'frida-gumjs-' + api_version,
  name: 'GumJS',
  version: gum_version,
  description: 'Gum JavaScript bindings',
  requires: ['frida-gum-' + api_version, 'json-glib-1.0'],
  requires_private: ['gio-2.0', 'libffi', 'capstone'] + gumjs_extra_requires,
  subdirs: install_header_basedir,
  libraries: [gumjs],
  variables: [
    'gumjs_qjs=' + quickjs_dep.found().to_string('enabled', 'disabled'),
    'gumjs_v8=' + v8_dep.found().to_string('enabled', 'disabled'),
  ],
)
